package sfeir.gwt.ergosum.client.profile;

import java.util.ArrayList;
import java.util.List;

import sfeir.gwt.ergosum.client.ClientApi;
import sfeir.gwt.ergosum.client.ClientApiAsync;
import sfeir.gwt.ergosum.client.ImportDialog;
import sfeir.gwt.ergosum.client.model.Address;
import sfeir.gwt.ergosum.client.model.Email;
import sfeir.gwt.ergosum.client.model.ImageURL;
import sfeir.gwt.ergosum.client.model.NetworkItem;
import sfeir.gwt.ergosum.client.model.Person;
import sfeir.gwt.ergosum.client.model.Tel;
import sfeir.gwt.ergosum.client.profile.text.RichTextToolbar;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;

public class EditProfile implements EntryPoint {

	private ClientApiAsync profileManager;

	private TextBox firstname, lastname, nickname, company, role, aliasLink;
	// private TextBox birthdate;
	private PushButton photo;
	private VerticalPanel photoPanel;
	private RichTextArea about;
	private FlexComboField phone, email, address;

	FlexNetworkField web;
	private Person p;
	private Button save;

	private HTML rbupload;
	private HTML rburl;
	private String photoURL;
	private Label aliasLinkError;

	private Boolean aliasCheck = false;

	private void initGUI() {
		RootPanel.get("content").clear();
		VerticalPanel root = new VerticalPanel();

		HorizontalPanel HPaliasLink = new HorizontalPanel();
		HPaliasLink.setStyleName("alias-link-panel");
		HPaliasLink.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		HPaliasLink.add(new Label("http://" + Window.Location.getHost()
				+ "/profile/"));
		aliasLink = new TextBox();
		aliasLink.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				aliasLinkError.setText("");
				String value = aliasLink.getText();
				aliasCheck = (p != null && value.equals(p.getAlias()));
				if (!value.matches("^([a-zA-Z0-9_.@+-])+$")) {
					aliasLink.addStyleName("form-input-error");
					aliasLinkError.setText("Just use alpha numeric charactere");
					aliasLinkError.setStyleName("alias-allready-used");
					aliasCheck = false;
					return;
				}
				if (!aliasCheck) {
					profileManager.checkAlias(value,
							new AsyncCallback<Boolean>() {

								@Override
								public void onFailure(Throwable caught) {
									GWT.log("Error with checkAlias", caught);
								}

								@Override
								public void onSuccess(Boolean result) {
									aliasCheck = result;
									if (result) {
										aliasLinkError.setText("Available");
										aliasLinkError
												.setStyleName("alias-available");
										aliasLink
												.removeStyleName("form-input-error");
									} else {
										aliasLinkError.setText("Already used");
										aliasLinkError
												.setStyleName("alias-allready-used");
									}
								}

							});
				}
			}
		});
		HPaliasLink.add(aliasLink);
		aliasLinkError = new Label();
		aliasLinkError.setWidth("80px");
		HPaliasLink.add(aliasLinkError);
		root.add(HPaliasLink);
		root.setCellHorizontalAlignment(HPaliasLink,
				HasHorizontalAlignment.ALIGN_CENTER);
		HorizontalPanel profile = new HorizontalPanel();
		profile.setWidth("100%");
		profile.setStyleName("mgbottom");
		HorizontalPanel contact = new HorizontalPanel();

		VerticalPanel mainInfos = new VerticalPanel();
		HorizontalPanel perso = new HorizontalPanel();

		setPersonalInfos(perso);// name, birthdate, photo, ...

		Grid pro = setProInfos();// company, role
		pro.setStyleName("mgtop");

		mainInfos.add(perso);
		mainInfos.add(pro);

		VerticalPanel aboutField = setAbout();// free text
		aboutField.setStyleName("mgleft");

		profile.add(mainInfos);
		profile.add(aboutField);
		root.add(profile);

		VerticalPanel contactMethods = setContactMethods();// phone, mail,
		// address

		contact.add(contactMethods);

		DecoratorPanel webid = new DecoratorPanel();
		web = new FlexNetworkField();// new
		// FlexComboField(FlexComboField.WEBURL);

		webid.add(web);

		contact.add(webid);

		root.add(contact);

		save = new Button("Save");
		save.addClickHandler(new ClickHandler() {

			@SuppressWarnings( { "unchecked", "null" })
			@Override
			public void onClick(ClickEvent event) {
				save.setEnabled(false);
				// Rebuild a person
				String name = lastname.getText();
				if (!aliasCheck) {
					aliasLink.addStyleName("form-input-error");
					Window.alert("You must set the url Alias");
					save.setEnabled(true);
					return;
				}
				List<Email> listEmail = (List<Email>) email.getDatas();
				if (name == null || name.equalsIgnoreCase("")) {
					if (listEmail != null && listEmail.size() > 0)
						name = ((Email) (listEmail.get(0))).getEmail();
				}

				if (name != null || !name.equalsIgnoreCase("")) {
					p = new Person();
					p.setName(name);
					p.setAlias(aliasLink.getText());
					String fn = firstname.getText();
					String nn = nickname.getText();
					// String birth = birthdate.getValue().toString();
					String comp = company.getText();
					String rol = role.getText();
					String abo = about.getHTML();

					if (!fn.equalsIgnoreCase(""))
						p.setFirstname(fn);
					if (!nn.equalsIgnoreCase(""))
						p.setNickname(nn);
					// if (!birth.equalsIgnoreCase(""))
					// p.setBirthDay(birth);
					if (!comp.equalsIgnoreCase(""))
						p.setCompany(comp);
					if (!rol.equalsIgnoreCase(""))
						p.setTitle(rol);
					if (!abo.equalsIgnoreCase(""))
						p.setAboutMe(abo);

					p.setTels((List<Tel>) (phone.getDatas()));
					p.setEmails(listEmail);
					p.setAddresses((List<Address>) (address.getDatas()));
					p.setNetworkItems((List<NetworkItem>) (web.getDatas()));

					if (photoURL != null && !photoURL.isEmpty())
						p.setPhoto(new ImageURL(photoURL));

					profileManager.createProfile(p, new AsyncCallback<Long>() {

						@Override
						public void onFailure(Throwable caught) {
							Window.alert("Failure " + caught.getMessage());
							save.setEnabled(true);
						}

						@Override
						public void onSuccess(Long result) {
							Window.alert("Profile saved");
							save.setEnabled(true);
						}
					});
				}
			}
		});
		save.setEnabled(false);// until profile is loaded
		root.add(save);
		root.setCellHorizontalAlignment(save, HasAlignment.ALIGN_RIGHT);
		RootPanel.get("content").getElement().setInnerText("");
		RootPanel.get("content").add(root);
	}

	private void loadDatas() {

		if (p != null) {
			String alias = p.getAlias();
			if (alias != null && !alias.isEmpty()) {
				aliasLink.setText(alias);
				aliasCheck = true;
			}
			firstname.setText(p.getFirstname());
			lastname.setText(p.getName());
			nickname.setText(p.getNickname());
			// birthdate.setText(p.getBirthDay());

			if (p.getNickname() != null)
				nickname.setText(p.getNickname());

			if (p.getPhoto() != null) {
				photoURL = p.getPhoto().getImageUrl();
				Image image = new Image(photoURL);

				if (image != null) {
					image.setPixelSize(80, 100);
					photo = new PushButton(image);

					photo.setPixelSize(80, 100);
					photo.addClickHandler(new ClickHandler() {

						@Override
						public void onClick(ClickEvent event) {
							showPhotoDialog();
						}
					});
					photoPanel.clear();
					photoPanel.add(photo);
				}
			}

			company.setText(p.getCompany());
			role.setText(p.getTitle());

			if (p.getTels() != null)
				phone.setRows((ArrayList<?>) p.getTels());
			if (p.getEmails() != null)
				email.setRows((ArrayList<?>) p.getEmails());
			if (p.getAddresses() != null)
				address.setRows((ArrayList<?>) p.getAddresses());

			String aboutString = p.getAboutMe();
			if (aboutString != null && !aboutString.equalsIgnoreCase(""))
				about.setHTML(aboutString);

			web.setRows((ArrayList<?>) p.getNetworkItems());
			web.setPerson(p);
			web.listMyNetworks();
			web.listAllNetworks();
		}
	}

	@Override
	public void onModuleLoad() {

		p = null;

		profileManager = GWT.create(ClientApi.class);
		profileManager.getUserProfile(new AsyncCallback<Person>() {

			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Person result) {
				p = result;
				save.setEnabled(true);
				loadDatas();
			}

		});

		initGUI();

		Element elt = DOM.getElementById("import");
		DOM.setEventListener(elt, new EventListener() {
			@Override
			public void onBrowserEvent(Event event) {
				if (Event.ONCLICK == event.getTypeInt())
					new ImportDialog().center();
			}
		});
		DOM.sinkEvents(elt, Event.ONCLICK);
	}

	/**
	 * Panel of FlexComboFields phone, email, and postal address
	 * 
	 * @return
	 */
	private VerticalPanel setContactMethods() {
		VerticalPanel contactMethods = new VerticalPanel();

		phone = new FlexComboField(FlexComboField.PHONE);
		email = new FlexComboField(FlexComboField.MAIL);
		address = new FlexComboField(FlexComboField.ADDRESS);

		contactMethods.add(phone);
		contactMethods.add(email);
		contactMethods.add(address);

		return contactMethods;
	}

	/**
	 * rich text area for "about me"
	 * 
	 * @return
	 */
	private VerticalPanel setAbout() {
		VerticalPanel aboutField = new VerticalPanel();
		HTML aboutLabel = new HTML("About me :");
		about = new RichTextArea();
		about.ensureDebugId("cwRichText-area");
		about.setSize("100%", "14em");
		RichTextToolbar toolbar = new RichTextToolbar(about);
		toolbar.ensureDebugId("cwRichText-toolbar");
		toolbar.setWidth("100%");

		// Add the components to a panel
		Grid grid = new Grid(2, 1);
		grid.setStyleName("cw-RichText");
		grid.setWidget(0, 0, toolbar);
		grid.setWidget(1, 0, about);
		aboutField.add(aboutLabel);
		aboutField.add(grid);
		return aboutField;
	}

	/**
	 * set the professionnal fields
	 * 
	 * @return Grid
	 */
	private Grid setProInfos() {
		Grid pro = new Grid(2, 2);
		HTML companyLabel = new HTML("Company : ");
		HTML roleLabel = new HTML("Role : ");

		company = new TextBox();
		company.setWidth("20em");
		role = new TextBox();
		role.setWidth("20em");

		pro.setWidget(0, 0, companyLabel);
		pro.setWidget(0, 1, company);
		pro.setWidget(1, 0, roleLabel);
		pro.setWidget(1, 1, role);
		return pro;
	}

	/**
	 * Set the names fields and the photo button
	 * 
	 * @param perso
	 */
	private void setPersonalInfos(HorizontalPanel perso) {
		/*
		 * The profile part names, about, photo, etc
		 */
		photoPanel = new VerticalPanel();
		photo = new PushButton();

		photo.setPixelSize(80, 100);
		photo.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				showPhotoDialog();
			}
		});

		photoPanel.add(photo);

		Grid names = new Grid(4, 2);

		HTML firstnameLabel = new HTML("Firstname : ");
		HTML lastnameLabel = new HTML("Lastname : ");
		HTML nicknameLabel = new HTML("Nickname : ");
		// HTML birthdateLabel = new HTML("Birthdate : ");

		firstname = new TextBox();
		lastname = new TextBox();
		nickname = new TextBox();
		// birthdate = new TextBox();

		names.setWidget(0, 0, firstnameLabel);
		names.setWidget(0, 1, firstname);
		names.setWidget(1, 0, lastnameLabel);
		names.setWidget(1, 1, lastname);
		names.setWidget(2, 0, nicknameLabel);
		names.setWidget(2, 1, nickname);
		// names.setWidget(3, 0, birthdateLabel);
		// names.setWidget(3, 1, birthdate);

		perso.add(photoPanel);
		perso.add(names);
	}

	/**
	 * Set the dialog form to change the profile's photo
	 */
	private void showPhotoDialog() {
		/*
		 * Here we'll build the photo dialog box
		 */
		final DialogBox photoDialog = new DialogBox();
		photoDialog.setText("Change you photo");
		final VerticalPanel dialogPanel = new VerticalPanel();
		dialogPanel.setSpacing(5);
		photoDialog.setWidget(dialogPanel);

		dialogPanel
				.add(new HTML(
						"You can either change your photo throught its <b>URL</b>, <br/>either by <b>Uploading</b> it",
						true));

		HorizontalPanel urlField = new HorizontalPanel();
		HorizontalPanel uploadField = new HorizontalPanel();

		final TextBox url = new TextBox();

		final FormPanel form = new FormPanel();
		form.setEncoding(FormPanel.ENCODING_MULTIPART);
		form.setMethod(FormPanel.METHOD_POST);
		form.setAction("/gwtergosum/import");

		final FileUpload upload = new FileUpload();
		upload.setName("photo");
		form.setWidget(upload);

		form.addSubmitHandler(new SubmitHandler() {// before
					@Override
					public void onSubmit(SubmitEvent event) {
						String[] ext = upload.getFilename().split("\\.");
						int size = ext.length;
						if (size > 0 && ext[size - 1].length() > 1) {
							if (!ext[size - 1].equalsIgnoreCase("jpg")
									&& !ext[size - 1].equalsIgnoreCase("png")
									&& !ext[size - 1].equalsIgnoreCase("jpeg")) {
								event.cancel();
								Window
										.alert("Only the .JPG, .JPEG, and .PNG formats are accepted");
							}
						}
					}
				});
		form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
			@Override
			public void onSubmitComplete(SubmitCompleteEvent event) {
				photoURL = event.getResults();
				if (!photoURL.contains("http://")) {
				    Window.alert("An error is occured when uploading your picture");
				    GWT.log(photoURL, null);
				}
				if (p != null)
					p.setPhoto(new ImageURL(photoURL));

				Image image = new Image(photoURL);

				if (image != null) {
					image.setPixelSize(80, 100);
					photo = new PushButton(image);

					photo.setPixelSize(80, 100);
					photo.addClickHandler(new ClickHandler() {

						@Override
						public void onClick(ClickEvent event) {
							showPhotoDialog();
						}
					});
					photoPanel.clear();
					photoPanel.add(photo);
				}

				 photoDialog.hide();
			}
		});
		rburl = new HTML("URL : ");
		rburl.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				url.setEnabled(true);
			}
		});
		rbupload = new HTML("Upload : ");

		urlField.add(rburl);
		urlField.add(url);

		uploadField.add(rbupload);
		uploadField.add(form);

		dialogPanel.add(urlField);
		dialogPanel.add(uploadField);

		HorizontalPanel buttons = new HorizontalPanel();
		buttons.setSpacing(10);

		Button cancel = new Button("Cancel");
		cancel.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				photoDialog.hide();
			}
		});

		Button ok = new Button("OK");
		ok.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				String urlString = url.getText();
				String filename = upload.getFilename();
				if (filename != null && !filename.equalsIgnoreCase("")) {

					if (filename.length() == 0) {
						Window.alert("Please choose a file to upload");
					} else {
						form.submit();
					}
				} else if (urlString != null && !urlString.equalsIgnoreCase("")) {
					if (p != null)
						p.setPhoto(new ImageURL(urlString));

					photoURL = urlString;
					photo.setHTML("<img src='" + photoURL + "' />");
					photo.getUpFace().setHTML("<img src='" + photoURL + "' />");
					photoDialog.hide();

				}

			}
		});

		buttons.add(cancel);
		buttons.add(ok);

		dialogPanel.add(buttons);
		dialogPanel.setCellHorizontalAlignment(buttons,
				HasAlignment.ALIGN_RIGHT);

		photoDialog.center();
		photoDialog.show();
	}
}
